|
Introduction -turn page- Reference List Menu Library |
The Menu Library |
The menus are a rather important aspect of any user interface. You are familiar with
the Finder menu: the upper line shows a variety of different entries. Using the mouse cursor to click on an entry
causes a box with several subentries to appear. Then you can use the mouse to select the desired item. Such menus are usually created with a resource editor that writes the required information into the resource fork of your program. From there, they then have to be identified using a number and a type, loaded by the program, and registered with the MacOS. All of this is much easier with EasyGem: You do not need an additional program, all menus are defined and managed with the use of simple and clearly arranged commands directly from within your program. Even a novice programmer can use EasyGem to create professional looking menus. |
2.1 Definition of Menus Let's start these instructions at the point where the programming commences: determining the appearance of the menus. First, of course, you need to have a clear picture of how the menus are supposed to look. Every menu has at least one menu title. This is usually the Apple menu from which the control fields are called. This menu allows the addition of exactly one additional menu item or menu entry. Most programmers place their copyright message right here. All other menu titles can be assigned freely and as desired. Thus, it is advisable to think about the names of the menu titles first, how many are supposed to be used, and which entries are to be registered for each respective menu title. The menu itself is then easily created from within the program using the following EasyGem commands: |
Make_Menu Apple$,Copyright$,R Copyright[,Menuname$] |
Begins menu definition. |
M_Title Title$ |
Determines menu title. |
M_Entry Txt$, R Entry |
Defines menu item. |
M_Line_Entry |
Defines menu line. |
End_Menu |
Ends menu definition. |
Make_Menu "Apple","About Invoicing",Fac M_Title "Invoices" M_Entry "Write Invoices",In M_Entry "Write Reminders",Re M_Entry "Quit Program",Qu End_Menu |
M_Show |
Displays menu. |
2.2 Structure of a Program with a Menu |
Easy_Init:'Initialize EasyGem Make_Menu(......... ) 'The definition of the menu with the help of 'M_Title and M_Entry instructions are shown here. End_Menu M_Show:'The menu is displayed. 'Query the menu here. 'Instructions on how to do that can be found 'in Easy_Mesag some pages ahead. Easy_Exit:'Unmount EasyGem. END |
This program outline displays the most important basics of programming menus with EasyGem: 1. Activate EasyGem with Easy_Init. Only then is it possible to work with EasyGem commands. 2. Program the definition describing how the menu will look. 2.1. Begin the definition process using Make_Menu. 2.2. Define title entries with M_Title. 2.3. Define the entries of the folding box using M_Entry. 2.4. End the definition process using End_Menu. 3. Display the defined and finalized menu with M_Show. 4. Query the menu using M_Waitmesag or Easy_Mesag. 5. At the end of the program: Exit and umount EasyGem with Easy_Exit. In many cases, it is necessary to turn of a menu in its entirety, for example, if a modal dialog box is being displayed or if the program execution should not be disturbed by menu activities of the user for other reasons. For this purpose, the command M_Hide exists. It will render the entire menu inactive, which means that the menu is still visible but cannot be accessed any longer. |
M_Hide |
Hide menu (menu is no longer accessible). The previously deactivated menu can be reactivated using M_Show. |
Already you can use the up to now introduced commands to create a small program. The sample program is meant to be an invoicing (calculation program) with entries for two menu titles: "Apple" (for the control fields and "Invoices" (for the functions of the invoicing tasks). The menu items "Write invoices," "Write reminders," and "Exit program" are supposed to be in the folded down part of the menu "Invoices" as soon as users move their mouse over this entry. Our little program, however, will not query the menu yet but instead will display it and after 5 seconds delete it again. |
Easy_Init Make_Menu "Apple","About the Invoicing",Fac M_Title "Invoices" M_Entry "Write Invoices",In M_Entry "Write Reminders",Re M_Entry "Quit Program",Qu End_Menu M_Show WAIT 5 Easy_Exit END |
2.3 Menu Query During these 5 seconds - when the menu was displayed - you might have tried to use the mouse to access the title bar to fold down an entry. If you tried this, you noticed that nothing happened, nothing was folded out. The reason for this is that EasyGem has not been asked yet to take care of such events as "mouse is in uppermost line," meaning, "fold down menu." In order to introduce the corresponding procedure, we have to cover some tasks in a bit more detail first. There are several types of tasks a user can carry out: windows can be modified (enlarged/reduced, moved, deleted, moved to the background, a slider bar can be set, etc.), and it is possible to work with the menu (fold down menus and click on individual entries). EasyGem offers a variety of different procedures, depending on whether users are supposed to work only with windows or with windows and menus. The simplest call of EasyGem, which only covers menu tasks of the user, is as follows: |
M_Waitmesag R Entry |
Waits for menu event. |
The procedure M_Waitmesag will take care of everything else for you: If the mouse moves into the area of the uppermost
line and if the mouse button is depressed, the corresponding menu will fold out. As soon as the user has selected
an entry from the folded down box, M_Waitmesag sets the variable Entry
accordingly and returns. If you still have the invoicing program from the previous sample stored in memory, you can use that program for a trial replacement, substituting the WAIT 5 with M_Waitmesag Entry. The modified program displays the menu header and waits until you folded down any of the menu boxes and have clicked on an item. Then the M_Waitmesag will return again, Easy_Exit will be called, and the program is terminated. Important: M_Waitmesag waits until a menu item has been selected by clicking on it with the mouse; only then will the control be returned to the program! If the menu query is supposed to take place on the side, meaning, your program is supposed to carry out other tasks at the same time it queries the menu, then you have to use Easy_Mesag: |
Easy_Mesag R Entry |
Queries the menu and returns either 0 (nothing clicked on) in Entry or the clicked on menu item. |
Easy_Mesag corresponds to M_Waitmesag, the only difference is that it does not wait until a menu item has been chosen. However, the query whether to fold down a box or not and which menu item has been chosen, only takes place within Easy_Mesag. It is therefore necessary to repeatedly call Easy_Mesag! Should you neglect to do so, e.g., call up Easy_Mesag only once, then only the mouse will be queried during the short time required for the execution of Easy_Mesag. No further queries of the mouse by EasyGem will take place after that, and the user can certainly move the mouse into the header - but with no effect. The proper use of Easy_Mesag is thus as follows: |
REPEAT Easy_Mesag Entry 'A short program part may be listed here. UNTIL End_Condition |
It is important that the "short program part" does not take too long to be executed. If that is the case, it is an indication that Easy_Mesag is not called often enough and the mouse is thus not queried as much as it should be. The result might be that the user takes the mouse to the title bar, but the menu will only fold down after a delay of half a second (the next time when Easy_Mesag is called, to be precise). |
2.4 Evaluating the Variable Entry Which menu item has been chosen by the user is returned in the variable Entry with M_Waitmesag as well as with Easy_Mesag. Nevertheless, when M_Waitmesag is being used, there is a delay until a menu item has been chosen. Easy_Mesag, however, can also return zero in Entry, namely at that exact point in time when no menu item has been clicked on for the moment. The difference is about the same as between INPUT$(1) and INKEY$. In the first case, the computer waits until a key has been pressed; if no key has been pressed yet, an empty string is reported in the latter case. It is really not that easy to express the information about which entry has been clicked on in one simple number. One could number the entries all the way through and then return the number of the entry in Entry, but what happens if an entry is added in the menu? All queries directed towards any of the entries following the new one are no longer accurate. That is the reason EasyGem has chosen a different path. You might remember the variable you have to indicate with every M_Entry. As we know, the syntax of M_Entry is as follows: |
M_Entry Txt$,R Entry |
Defines menu item. |
Entry then will return the internal ID number of the respective entry. This number will be returned later by M_Waitmesag and Easy_Mesag as well. A simple comparison will then determine whether the respective entry has been chosen or not. The number itself may remain unknown to you. |
1. You define your menu with Make_Menu, M_Title,
M_Entry, and End_Menu. Every time you use M_Entry, you indicate a variable. The invoicing
program - already known to us - may serve as an example. There, we used the variables Fac,
In, Re, and Qu. 2. You call M_Waitmesag or Easy_Mesag, and the variable Entry is returned to you. 3. In order to determine which entry has been chosen, compare Entry with Fac, In, Re, and Qu. If Entry equals Fac, the menu item "About Invoicing" has been chosen; if Entry equals In, the entry "Write Invoices" has been selected, and so forth. If Entry equals zero, nothing has been clicked on (this response is only possible with Easy_Mesag; if nothing has been clicked on, M_Waitmesag does not return anything. 4. Depending on the selections made, your program can now respond appropriately. The following sample program displays a small menu on the screen and outputs the respective name of each menu item that has been clicked on. The program can be exited by choosing "End". |
Easy_Init 'Definition part. Make_Menu "Apple","About this Demo",Demo M_Title "Action" M_Entry "Text 1",T1 M_Entry "Text 2",T2 M_Entry "Text 3",T3 M_Entry "End",End End_Menu 'End definition part. M_Show:'Menu will be displayed. REPEAT M_Waitmesag X IF X=Demo THEN PRINT @(0,30);"About this Demo" IF X=T1 THEN PRINT @(0,30);"Text 1 " IF X=T2 THEN PRINT @(0,30);"Text 2 " IF X=T3 THEN PRINT @(0,30);"Text 3 " UNTIL X=End Easy_Exit:'Program ends: EasyGem is unmounted. END |
2.5 Menu Attributes You might have seen menus already that offer a variety of extras. Some entries could not be chosen (indicated by the letters being grayed out); some entries have little check marks or a symbol next to them; there are entries represented by a different font than the other entries, or entries, which have an assigned keyboard shortcut; and finally, there are programs, which change their entries while they are being run. All of that you can achieve with EasyGem as well and as easy as the creation of the menus themselves. An attribute is considered to be a characteristic of a menu item. If the attribute is "checked," it means that a check mark is next to the menu item. If an attribute is "disabled," it is represented as being grayed out and cannot be selected. With EasyGem you can easily change the attributes of all menu entries. For example, in order to set the attribute "checked," all you need to do is call M_Check: |
M_Check Entry |
Assigns the attribute "checked" (the check mark) to the menu item Entry. |
In this case, Entry once again denotes the internal ID number of the respective menu item. This internal ID number has already been returned by M_Entry in the definition of the menu. Consequently, you can always just indicate the variable for Entry that you have also used with M_Entry. |
Make_Menu "Apple","Info",Info M_Title "File" M_Entry "With check mark!",Mmark M_Entry " Quit ",Mquit End_Menu M_Check Mmark:'The entry "With check mark!" is here 'equipped with the attribute "checked." 'As soon as the box unfolds, the entry will have 'a check mark next to it. |
As you can see, the variable Mmark is simply indicated in the case of M_Check. This convention is the central thread running through all of EasyGem. The variable Mmark denotes the entry "With
check mark!" Any time this entry is the intended target, one either explicitly
indicates the variable Mmark
(as in the case of M_Check),
or one compares using this variable (as in the case of M_Waitmesag or Easy_Mesag
). In order to clarify the subject at hand, you can substitute the line |
IF X=T1 THEN PRINT @(l0,20);"Text 1 " |
IF X=T1 THEN M_Check T1 |
Now, if the menu item "Text 1" is being clicked on, it will then be assigned the attribute "checked," meaning
that a check mark will be placed next to it. Each menu item has to have that variable representing the entry, which has been indicated when the menu item was defined with M_Entry. Of course, there are numerous other types of attributes and assigned commands, which are listed here as follows: |
Attribute "checked" (preceding check mark): |
M_Check Entry |
Set. |
M_Uncheck Entry |
Delete. |
Attribute "disabled" (grayed out - cannot be selected): |
M_Disable Entry |
Set. |
M_Enable Entry |
Delete. |
Note: This command may also be used to "disable" or "enable" the menu bar itself and all corresponding entries. To accomplish this, you have to use the first entry under this menu title for Entry and subtract 1. |
Attribute "crossed" (crossed out rectangular or square): |
M_Cross Entry |
Set. |
M_Uncross Entry |
Delete. |
Attribute "style" (changes font): |
M_Style Entry,Style |
Style has to receive the same value as the BASIC command TEXT STYLE. |
Attribute "mark" (set mark): |
M_Mark Entry,Mark |
Mark has to contain the ASCII code of the symbol or character, which is to be placed next to the menu. |
Delete all attributes: |
M_Normal Entry |
The entry is once again displayed normally (without any attributes). |
Maybe some menu entries are supposed to be available via a keyboard shortcut as well. In this case, Apple has determined that the command key - together with a normal key - should be used for this purpose. Capital letters and small letters are used indiscriminately in this case. EasyGem offers a command to set these so-called shortcuts as well: |
Attribute "shortcut" (define key): |
M_Command Entry,Cmd |
For Cmd, please indicate the ASCII code of the character which is supposed to trigger the menu item. |
Note: If Cmd=0 is indicated, the shortcut will be removed again.
Sometimes it is necessary to change the text of a menu item during the execution of a program. For example, depending on what type of contents an uppermost window contains, an UNDO function might apply at one time to text and at another time to graphics. In order for the user to know which type of task can be reversed, the text in the menu item should be adapted accordingly. |
The following command can be used for this: |
M_Text Entry,Txt$ |
Any string expression may be passed in Txt$ (max. 255 characters). |
Sometimes it is necessary to be able to query whether or not an entry has a specific attribute. EasyGem offers functions for this task as well: |
Querying for "checked" (check mark): |
FN M_Checked(Entry) |
Returns -1, if the entry is "checked," otherwise 0. |
Querying for "disabled" (grayed out - cannot be selected): |
FN M_Enabled(Entry) |
Returns -1, if the entry is "enabled," (if entry can be selected), otherwise 0. |
Querying for "crossed" (crossed out rectangular or square): |
FN M_Crossed(Entry) |
Returns -1, if the entry is "crossed," otherwise 0. |
Querying for "style" (font of menu item): |
FN M_Style(Entry) |
Returns the text style (significance is same as for TEXT STYLE). |
Querying for "mark" (marking of the menu item): |
FN M_Mark(Entry) |
Returns the ASCII code of the marking of the menu item. |
Querying for "shortcut" (shortcut for menu item): |
FN M_Command(Entry) |
Returns the ASCII code of the shortcut belonging to the menu item. |
Querying for "text" (text of the menu item): |
FN M_Text$(Entry) |
Returns text of the menu item as a string. |
For example, in order to query our demo program whether the entry "Text 1" has been "checked" or not, the following program line has to be added: |
IF FN M_Checked(T1) THEN PRINT "With check mark" ELSE PRINT "Without check mark!" ENDIF |
This illustrates the fact that the attributes may be set even though the menu has not
been displayed yet. However, the up to now discussed functions and procedures only function correctly if the menu
definition has already been concluded - after End_Menu has been executed. If you would like to assign a certain attribute to an entry right from the start, you can choose a different path (example is for attribute "checked"): Simply write the call M_Check (without parameter) in the line containing the M_Entry. Write M_Check directly behind M_Entry itself. This would then look as follows: |
M_Entry "Text 3",T3:M_Check 'This entry is now being 'checked, meaning, it will receive a check mark. |
All other attributes can be handled completely analogously:
M_Disable |
"Disable" entry at once. |
M_Check |
"Check" entry at once. |
M_Cross |
"Cross" entry at once. |
M_Style Style |
Set font style. |
M_Mark Mark |
Set mark. |
M_Command Cmd |
Set shortcut. |
The appropriate and corresponding attribute is set in each case. In order for EasyGem
to know which menu item is targeted by which command, these calls have to be written directly behind the M_Entry to which they apply. Incidentally, a reverse function does not exist. If an entry is not supposed to be "crossed," then simply omit indicating M_Cross. Another optional method to assign menu attributes already during the definition phase is to use so-called meta-characters. These can be written immediately behind the text of the respective menu item. The following meta-characters exist: |
! |
The letter behind the exclamation mark is used to mark the beginning of the entry (e.g., the diamond-shaped symbol or check mark). |
< |
This may be used to determine the text attributes of the menu. To achieve this task, the letters B (bold), I (italic), U (underline), O (outline), and S (shadow) are used. Several of these letters may also be listed simultaneously behind the 'less than' symbol. |
/ |
Serves to determine the keyboard shortcuts for this menu item. |
( |
The entry will be disabled, is therefore no longer selectable. |
For example, in order to define a menu item called "Print", which can also be triggered by the shortcut [Cmd] + [P] and which is at first "disabled", because after the program's initial start there are no documents loaded as of yet which might be available for printing, the following command has to be used: |
M_Entry "Print/P(",Prn |
Note: Of course, as
soon as a document has been loaded that is also printable, you have to use M_Enable to ensure that the menu item "Print" becomes selectable. Since all good things come in threes, EasyGem offers yet another option to assign attributes while the menu items are being defined. The following four commands may be used to that effect: |
M_Disabled_Entry Txt$,R Entry |
Defines an entry analogously to M_Entry, with the difference that the entry is "disabled" at once. |
M_Checked_Entry Txt$,R Entry |
Defines an entry analogously to M_Entry, with the difference that the entry is "checked" at once. |
M_Crossed_Entry Txt$,R Entry |
Defines an entry analogously to M_Entry, with the difference that the entry is "crossed" at once. |
M_Disabled_Entry Txt$ |
Corresponds to M_Disabled_Entry Text$,R Entry, with the difference that no identifying variable is returned here. This means that the entry cannot be queried, a condition that is hardly serious, since the entry cannot be clicked on at any rate. |
The individual items or entries of a menu can often be sorted according to specific function groups, e.g., functions that open windows, others that close windows, or functions that print the contents of windows. In order to separate these individual function groups it is best to draw a continuous line into the menu. The following EasyGem command will draw this line: |
M_Line_Entry |
Defines continuous line. |
2.6 Deleting a Menu It is rather uncommon to want to delete an already defined menu during the lifetime of a program, but there might be special circumstances requiring this action. In order to meet any and all requirements, the EasyGem Library offers a command to delete a menu as well: |
Clear_Menu |
Delete menu. |
2.7 Managing Several Menus Using EasyGem If one menu suffices for your programs there is no need for you to read the remainder of this chapter. If, however, you would like to use several, individual menus from within one program, you need to apply the following procedures and functions. The use of more than one menu requires a way to differentiate between the individual menus. EasyGem makes use of another parameter, which has to be included with all commands necessary to identify a specific menu. This identification number will be returned to you after the definition has been concluded with End_Menu. A variable has to be indicated behind End_Menu to achieve this task. This variable may then be used for all future calls. |
End_Menu R Menu_Id |
Corresponds to End_Menu, but returns the identification number of the just defined menu as well. |
The definition of a menu using Make_Menu, M_Title
and M_Entry (or M_Disabled_Entry, or, or ... ) is performed
the same way for several menus as it is for defining only one. However, a variable has to be indicated when using
End_Menu, which will then contain
the identification number of the just defined menu. The difference between a single menu and several ones subsequently
consists of the fact that several Make_Menu commands with the corresponding End_Menu commands are present in programs with more than one menu. Each menu
receives its own, unmistakable identification number through the use of End_Menu. Once the menus are finalized and defined, those commands which are already known to us can be used on these menus. Of course, it is impossible to display two menus at the same time, but what is possible is to turn off one menu and to display another one in its place. The M_Show command is equipped with the identification number of the desired menu as an additional parameter to achieve this task. |
M_Show Menu_Id |
Displays the menu with the identification number Menu_Id. |
Note: The menu for the Omikron Basic output window will be displayed if you indicate Menu_Id=0. Naturally, this only functions if you have also defined an Omikron Basic output window as well. |
FN M_Which |
Determines the identification number of the displayed menu. |
Since the management of several menus differs from the management for one menu only by the additional parameter Menu_Id but all other management tasks and functions remain the same, we will refrain from explaining them all once more at this point. However, the following table lists them in their entirety. |
M_Check Menu_Id,Entry |
M_Uncheck Menu_Id,Entry |
M_Disable Menu_Id,Entry |
M_Enable Menu_Id,Entry |
M_Cross Menu_Id,Entry |
M_Uncross Menu_Id,Entry |
M_Style Menu_Id,Entry,Style |
M_Mark Menu_Id,Entry,Mark |
M_Normal Menu_Id,Entry |
M_Command Menu_Id,Entry,Cmd |
M_Text Menu_Id,Entry,Txt$ |
FN M_Checked(Menu_Id,Entry) |
FN M_Enabled(Menu_Id,Entry) |
FN M_Crossed(Menu_Id,Entry) |
FN M_Style(Menu_Id,Entry) |
FN M_Mark(Menu_Id,Entry) |
FN M_Command(Menu_Id,Entry) |
FN M_Text$(Menu_Id,Entry) |
Clear_Menu Menu_Id |
As always, the actual use of these EasyGem commands are best illustrated using an example: |
Easy_Init:'Initializes EasyGem. 'Define first menu. Make_Menu "Apple","About this program",Copyright1 M_Title "File" M_Entry "Load",M_Load M_Title "View" M_Entry "Change",M_Change M_Title "Info" M_Entry "About Menus",M_Menu M_Title "Draw" M_Entry "Hobgoblin",M_Hobgoblin M_Title "Screen" M_Entry "Clear",M_Clear M_Title "Menu 1" M_Entry "To Menu 2",To_Menu2 M_Entry "Quit",M_Quit1 End_Menu Menu1 'Define second menu. Make_Menu "Apple","About this program",Copyright2 M_Title "File" M_Entry "Save",M_Save M_Title "View" M_Entry "Restore",M_Restore M_Title "Info" M_Entry "About Dialogs",M_Dialog M_Title "Draw" M_Entry "Important",M_Important M_Title "Screen" M_Entry "Fill",M_Fill M_Title "Menu 2" M_Entry "To Menu 1",To_Menu1 M_Entry "Quit",M_Quit2 End_Menu Menu2 'Display Menu 1. M_Show Menu1 'At this point, the program waits for 'any menu activity. REPEAT: M_Waitmesag Entry IF FN M_Which=Menu1 THEN IF Entry=M_Quit1 THEN EXIT IF Entry=To_Menu2 THEN M_Show Menu2 'More queries for Menu1. ELSE IF Entry=M_Quit2 THEN EXIT IF Entry=To_Menu1 THEN M_Show Menu1 'More queries for Menu2. ENDIF UNTIL 0:'Infinite Loop. Easy_Exit:'Unmounts EasyGem again. END |
Note: If your program initially needs only one menu but might require additional menus further down the line, you should include Menu_Id right from the start. This will save a lot of time and effort in reprogramming the parts for the first menu if and when you decide to add additional menus. It might also be sensible to save the identification numbers as well as the reference numbers for the individual entries and items in fields in case numerous menus are needed. Saving this information in fields will make it more obvious which entries are assigned to which menus. |
2.8 Guidelines for Programming Menus Please note that the preceding examples and sample programs were created using random menu items. They only served the purpose of explaining diverse EasyGem functions and should not be used as the basic for finished programs. Certain rules have become established regarding the creation of menus, which, if at all possible, should be adhered to in the interest of a unified and standardized operationability of different programs. Each menu should start with the menu titles "File" and "Edit" and offer a few basic functions for each of these: |
Make_Menu " Apple ","About this program",Copyright M_Title "File" M_Entry "New/N",New1 M_Entry "Open ... /O",Open1 M_Line_Entry M_Entry "Close/W",Close1 M_Entry "Save/S",Save1 M_Entry "Save As ... ",Save_As1 M_Entry "Page Setup ... ",Page_Setup1 M_Entry "Print ... /P",Print1 M_Line_Entry M_Entry "Quit/Q",Quit1 M_Title "Edit" M_Entry "Undo/Z",Undo1 M_Line_Entry M_Entry "Cut/X",Cut1 M_Entry "Copy/C",Copy1 M_Entry "Paste/V",Paste1 M_Entry "Clear",Clear1 End_Menu Menu1 |
Introduction -turn page- Reference List Menu Library |
© 1998-1999 Berkhan-Software www.berkhan.com | Home |